package com.douyin.controller;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * 媒体代理控制器 - 解决微信小程序无法直接访问外链的问题
 * 通过后端代理转发视频流和图片，解决跨域和域名白名单限制
 */
@Slf4j
@RestController
@RequestMapping("/video-proxy")
public class VideoProxyController {

    private static final int BUFFER_SIZE = 8192;
    private static final int TIMEOUT = 30000; // 30秒超时
    
    /**
     * 代理视频流接口
     * GET方式，直接通过URL参数传递视频链接
     */
    @GetMapping
    public void proxyVideoStream(@RequestParam("url") String videoUrl, HttpServletResponse response) {
        log.info("🎬 开始代理视频流: {}", videoUrl.substring(0, Math.min(100, videoUrl.length())) + "...");
        
        try {
            // 验证URL是否为抖音相关域名
            if (!isValidDouyinVideoUrl(videoUrl)) {
                log.warn("❌ 无效的视频URL: {}", videoUrl);
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            
            // 请求原始视频流
            HttpResponse videoResponse = HttpRequest.get(videoUrl)
                    .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                    .header("Referer", "https://www.douyin.com/")
                    .header("Accept", "*/*")
                    .header("Accept-Language", "zh-CN,zh;q=0.9")
                    .timeout(TIMEOUT)
                    .execute();
            
            int statusCode = videoResponse.getStatus();
            log.info("📡 上游响应状态码: {}", statusCode);
            
            if (statusCode != 200 && statusCode != 206) {
                log.warn("❌ 上游服务器响应异常: {}", statusCode);
                response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
                return;
            }
            
            // 设置响应头
            response.setContentType("video/mp4");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type");
            
            // 传递内容长度（如果有）
            String contentLength = videoResponse.header("Content-Length");
            if (contentLength != null && !contentLength.trim().isEmpty()) {
                response.setHeader("Content-Length", contentLength);
                log.info("📏 视频文件大小: {} bytes", contentLength);
            }
            
            // 支持断点续传
            String acceptRanges = videoResponse.header("Accept-Ranges");
            if (acceptRanges != null) {
                response.setHeader("Accept-Ranges", acceptRanges);
            }
            
            String contentRange = videoResponse.header("Content-Range");
            if (contentRange != null) {
                response.setHeader("Content-Range", contentRange);
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            }
            
            // 流式传输视频数据
            long bytesTransferred = 0;
            try (InputStream inputStream = videoResponse.bodyStream();
                 OutputStream outputStream = response.getOutputStream()) {
                
                byte[] buffer = new byte[BUFFER_SIZE];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    bytesTransferred += bytesRead;
                    
                    // 每传输1MB记录一次日志
                    if (bytesTransferred % (1024 * 1024) == 0) {
                        log.debug("🚀 已传输: {} MB", bytesTransferred / (1024 * 1024));
                    }
                }
                
                outputStream.flush();
                log.info("✅ 视频流代理完成，总传输: {} bytes", bytesTransferred);
            }
            
        } catch (Exception e) {
            log.error("❌ 视频代理失败: {}", e.getMessage(), e);
            if (!response.isCommitted()) {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        }
    }
    
    /**
     * POST方式代理接口（兼容性）
     */
    @PostMapping
    public void proxyVideoPost(@RequestBody Map<String, String> request, HttpServletResponse response) {
        String videoUrl = request.get("url");
        if (videoUrl == null || videoUrl.trim().isEmpty()) {
            log.warn("❌ POST请求缺少url参数");
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        
        proxyVideoStream(videoUrl, response);
    }
    
    /**
     * OPTIONS预检请求支持
     */
    @RequestMapping(method = RequestMethod.OPTIONS)
    public void handleOptions(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        response.setStatus(HttpServletResponse.SC_OK);
    }
    
    /**
     * 媒体下载代理接口 - 支持图片和视频下载
     */
    @GetMapping("/download")
    public void downloadMedia(@RequestParam("url") String mediaUrl, 
                            @RequestParam(value = "type", defaultValue = "auto") String mediaType,
                            HttpServletResponse response) {
        log.info("📥 开始代理下载媒体: {}", mediaUrl.substring(0, Math.min(100, mediaUrl.length())) + "...");
        
        try {
            // 验证URL是否为有效的媒体URL
            if (!isValidMediaUrl(mediaUrl)) {
                log.warn("❌ 无效的媒体URL: {}", mediaUrl);
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            
            // 自动检测媒体类型
            String detectedType = detectMediaType(mediaUrl, mediaType);
            log.info("🔍 检测到媒体类型: {}", detectedType);
            
            // 请求原始媒体文件
            HttpResponse mediaResponse = HttpRequest.get(mediaUrl)
                    .header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1")
                    .header("Referer", "https://www.douyin.com/")
                    .header("Accept", "*/*")
                    .header("Accept-Language", "zh-CN,zh;q=0.9")
                    .timeout(TIMEOUT)
                    .execute();
            
            int statusCode = mediaResponse.getStatus();
            log.info("📡 上游响应状态码: {}", statusCode);
            
            if (statusCode != 200 && statusCode != 206) {
                log.warn("❌ 上游服务器响应异常: {}", statusCode);
                response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
                return;
            }
            
            // 设置响应头
            setDownloadHeaders(response, detectedType, mediaUrl);
            
            // 传递内容长度（如果有）
            String contentLength = mediaResponse.header("Content-Length");
            if (contentLength != null && !contentLength.trim().isEmpty()) {
                response.setHeader("Content-Length", contentLength);
                log.info("📏 媒体文件大小: {} bytes", contentLength);
            }
            
            // 流式传输媒体数据
            long bytesTransferred = 0;
            try (InputStream inputStream = mediaResponse.bodyStream();
                 OutputStream outputStream = response.getOutputStream()) {
                
                byte[] buffer = new byte[BUFFER_SIZE];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    bytesTransferred += bytesRead;
                    
                    // 每传输1MB记录一次日志
                    if (bytesTransferred % (1024 * 1024) == 0) {
                        log.debug("🚀 已传输: {} MB", bytesTransferred / (1024 * 1024));
                    }
                }
                
                outputStream.flush();
                log.info("✅ 媒体下载代理完成，总传输: {} bytes", bytesTransferred);
            }
            
        } catch (Exception e) {
            log.error("❌ 媒体下载代理失败: {}", e.getMessage(), e);
            if (!response.isCommitted()) {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        }
    }
    
    /**
     * 设置下载响应头
     */
    private void setDownloadHeaders(HttpServletResponse response, String mediaType, String url) {
        // 基础CORS头
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type");
        
        // 设置Content-Type和文件扩展名
        String filename = generateFilename(url, mediaType);
        
        if ("video".equals(mediaType)) {
            response.setContentType("video/mp4");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".mp4\"");
        } else if ("image".equals(mediaType)) {
            // 根据URL判断图片格式
            if (url.toLowerCase().contains(".webp")) {
                response.setContentType("image/webp");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".webp\"");
            } else if (url.toLowerCase().contains(".jpg") || url.toLowerCase().contains(".jpeg")) {
                response.setContentType("image/jpeg");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".jpg\"");
            } else if (url.toLowerCase().contains(".png")) {
                response.setContentType("image/png");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".png\"");
            } else {
                response.setContentType("image/jpeg");
                response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".jpg\"");
            }
        } else {
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
        }
    }
    
    /**
     * 生成文件名
     */
    private String generateFilename(String url, String mediaType) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        if ("video".equals(mediaType)) {
            return "douyin_video_" + timestamp;
        } else if ("image".equals(mediaType)) {
            return "douyin_image_" + timestamp;
        } else {
            return "douyin_media_" + timestamp;
        }
    }
    
    /**
     * 检测媒体类型
     */
    private String detectMediaType(String url, String providedType) {
        if (!"auto".equals(providedType)) {
            return providedType;
        }
        
        String lowerUrl = url.toLowerCase();
        
        // 检查是否是视频URL
        if (lowerUrl.contains("douyinvod.com") || 
            lowerUrl.contains("/aweme/v1/play") || 
            lowerUrl.contains(".mp4") ||
            lowerUrl.contains("video")) {
            return "video";
        }
        
        // 检查是否是图片URL
        if (lowerUrl.contains(".jpg") || lowerUrl.contains(".jpeg") || 
            lowerUrl.contains(".png") || lowerUrl.contains(".webp") ||
            lowerUrl.contains("image")) {
            return "image";
        }
        
        // 默认返回video（因为大部分是视频）
        return "video";
    }
    
    /**
     * 验证是否为有效的媒体URL - 扩展支持更多域名
     */
    private boolean isValidMediaUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return false;
        }
        
        // 允许的媒体域名（视频和图片）
        return url.startsWith("https://") && (
                // 抖音视频域名
                url.contains("douyinvod.com") ||
                url.contains("ixigua.com") ||
                url.contains("douyincdn.com") ||
                url.contains("iesdouyin.com") ||
                url.contains("aweme.snssdk.com") ||
                url.contains("douyin.com") ||
                // 抖音图片域名
                url.contains("p3-pc-sign.douyinpic.com") ||
                url.contains("p6-pc-sign.douyinpic.com") ||
                url.contains("p9-pc-sign.douyinpic.com") ||
                url.contains("douyinpic.com") ||
                url.contains("snssdk.com") ||
                // TikTok域名
                url.contains("tiktokcdn.com") ||
                url.contains("tiktok.com") ||
                // 其他常见CDN
                url.contains("bytedance.com") ||
                url.contains("muscdn.com")
        );
    }
    
    /**
     * 验证是否为有效的抖音视频URL（保持向后兼容）
     */
    private boolean isValidDouyinVideoUrl(String url) {
        return isValidMediaUrl(url) && detectMediaType(url, "auto").equals("video");
    }
    
    /**
     * 获取代理URL
     * 工具方法，供前端调用时生成正确的代理链接
     */
    @GetMapping("/generate-proxy-url")
    public Map<String, String> generateProxyUrl(@RequestParam("original") String originalUrl) {
        try {
            if (!isValidDouyinVideoUrl(originalUrl)) {
                return Map.of("success", "false", "message", "无效的视频URL");
            }
            
            // 生成代理URL
            String proxyUrl = "/api/video-proxy?url=" + java.net.URLEncoder.encode(originalUrl, "UTF-8");
            
            return Map.of(
                "success", "true", 
                "proxyUrl", proxyUrl,
                "originalUrl", originalUrl,
                "message", "代理URL生成成功"
            );
        } catch (Exception e) {
            log.error("生成代理URL失败: {}", e.getMessage());
            return Map.of("success", "false", "message", "生成代理URL失败: " + e.getMessage());
        }
    }
}